Comprehensive Course Material
A list in Python is an ordered, mutable collection of items. Lists are one of the most versatile and commonly used data structures in Python, allowing you to store multiple items in a single variable.
# Creating a simple list
fruits = ["apple", "banana", "cherry"]
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]
There are several ways to create lists in Python:
# Empty list
empty_list = []
also_empty = list()
# List with initial values
colors = ["red", "green", "blue"]
# Using list() constructor
letters = list("hello") # ['h', 'e', 'l', 'l', 'o']
# List comprehension (covered later)
squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16]
Python uses zero-based indexing, meaning the first element is at index 0.
fruits = ["apple", "banana", "cherry", "date"]
print(fruits[0]) # "apple"
print(fruits[2]) # "cherry"
print(fruits[-1]) # "date" (last element)
print(fruits[-2]) # "cherry" (second from end)
You can extract portions of a list using slice notation: list[start:stop:step]
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(numbers[2:5]) # [2, 3, 4] (index 2 to 4)
print(numbers[:4]) # [0, 1, 2, 3] (start to index 3)
print(numbers[6:]) # [6, 7, 8, 9] (index 6 to end)
print(numbers[::2]) # [0, 2, 4, 6, 8] (every 2nd element)
print(numbers[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] (reversed)
fruits = ["apple", "banana", "cherry"]
fruits[1] = "blueberry"
print(fruits) # ["apple", "blueberry", "cherry"]
# append() - adds to the end
fruits = ["apple", "banana"]
fruits.append("cherry")
print(fruits) # ["apple", "banana", "cherry"]
# insert() - adds at specific position
fruits.insert(1, "blueberry")
print(fruits) # ["apple", "blueberry", "banana", "cherry"]
# extend() - adds multiple elements
fruits.extend(["date", "elderberry"])
# Using + operator
more_fruits = fruits + ["fig", "grape"]
fruits = ["apple", "banana", "cherry", "date"]
# remove() - removes first occurrence of value
fruits.remove("banana")
# pop() - removes and returns element at index
last_fruit = fruits.pop() # removes last element
first_fruit = fruits.pop(0) # removes first element
# del - removes element(s)
del fruits[1] # removes element at index 1
del fruits[1:3] # removes slice
# clear() - removes all elements
fruits.clear()
print(fruits) # []
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print(len(numbers)) # 8
print(min(numbers)) # 1
print(max(numbers)) # 9
print(sum(numbers)) # 31
fruits = ["apple", "banana", "cherry"]
print("apple" in fruits) # True
print("grape" in fruits) # False
print("grape" not in fruits) # True
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
# sort() - modifies the list in place
numbers.sort()
print(numbers) # [1, 1, 2, 3, 4, 5, 6, 9]
# sort in reverse
numbers.sort(reverse=True)
# sorted() - returns new sorted list
original = [3, 1, 4, 1, 5]
sorted_list = sorted(original)
print(original) # [3, 1, 4, 1, 5] (unchanged)
print(sorted_list) # [1, 1, 3, 4, 5]
fruits = ["apple", "banana", "cherry"]
# reverse() - modifies list in place
fruits.reverse()
print(fruits) # ["cherry", "banana", "apple"]
# reversed() - returns iterator
reversed_fruits = list(reversed(fruits))
numbers = [1, 2, 3, 2, 4, 2, 5]
# count() - counts occurrences
print(numbers.count(2)) # 3
# index() - finds first occurrence
print(numbers.index(2)) # 1
print(numbers.index(2, 2)) # 3 (start searching from index 2)
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
# Using enumerate()
for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")
# Output:
# 0: apple
# 1: banana
# 2: cherry
fruits = ["apple", "banana", "cherry"]
i = 0
while i < len(fruits):
print(fruits[i])
i += 1
List comprehensions provide a concise way to create lists based on existing lists or other iterables.
# Traditional approach
squares = []
for x in range(10):
squares.append(x**2)
# List comprehension
squares = [x**2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# Only even numbers
evens = [x for x in range(20) if x % 2 == 0]
# Uppercase only for words starting with 'a'
fruits = ["apple", "banana", "apricot", "cherry"]
a_fruits = [f.upper() for f in fruits if f.startswith('a')]
print(a_fruits) # ['APPLE', 'APRICOT']
# Create a 3x3 matrix
matrix = [[i + j for j in range(3)] for i in range(3)]
print(matrix) # [[0, 1, 2], [1, 2, 3], [2, 3, 4]]
# Flatten a matrix
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
Lists can contain other lists, creating multidimensional structures.
# 2D list (matrix)
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# Accessing elements
print(matrix[0][0]) # 1
print(matrix[1][2]) # 6
print(matrix[2][1]) # 8
# Iterating through 2D list
for row in matrix:
for element in row:
print(element, end=' ')
print() # New line after each row
# Using slice
original = [1, 2, 3]
copy1 = original[:]
# Using copy()
copy2 = original.copy()
# Using list()
copy3 = list(original)
# Problem with nested lists (shallow copy)
original = [[1, 2], [3, 4]]
shallow = original.copy()
shallow[0][0] = 999
print(original) # [[999, 2], [3, 4]] - original is affected!
import copy
original = [[1, 2], [3, 4]]
deep = copy.deepcopy(original)
deep[0][0] = 999
print(original) # [[1, 2], [3, 4]] - original is unaffected
print(deep) # [[999, 2], [3, 4]]
fruits = ["apple", "banana", "cherry"]
# Basic unpacking
a, b, c = fruits
print(a) # "apple"
# Using * for remaining elements
first, *rest = fruits
print(first) # "apple"
print(rest) # ["banana", "cherry"]
first, *middle, last = [1, 2, 3, 4, 5]
print(middle) # [2, 3, 4]
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
cities = ["New York", "London", "Paris"]
# Combine multiple lists
combined = list(zip(names, ages, cities))
print(combined)
# [('Alice', 25, 'New York'), ('Bob', 30, 'London'), ('Charlie', 35, 'Paris')]
# Unzip
names2, ages2, cities2 = zip(*combined)
numbers = [1, 2, 3, 4, 5]
# Map - apply function to each element
squared = list(map(lambda x: x**2, numbers))
print(squared) # [1, 4, 9, 16, 25]
# Filter - keep elements that satisfy condition
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # [2, 4]
numbers = [3, -1, 4, -5, 9, 2]
# Maximum absolute value
max_abs = max(numbers, key=abs)
print(max_abs) # 9
# Longest string
words = ["cat", "elephant", "dog"]
longest = max(words, key=len)
print(longest) # "elephant"
stack = []
stack.append(1) # Push
stack.append(2)
stack.append(3)
print(stack.pop()) # 3 (Pop)
print(stack.pop()) # 2
collections.deque instead of lists for better performance.
# Better to use collections.deque for queues
from collections import deque
queue = deque([1, 2, 3])
queue.append(4) # Add to right
print(queue.popleft()) # Remove from left: 1
Python lists are powerful and flexible data structures that support a wide range of operations including adding, removing, sorting, and searching elements. Understanding lists is fundamental to Python programming, and mastering list comprehensions can make your code more concise and Pythonic.
Remember that lists are mutable, which means they can be changed after creation, and this has implications for copying and passing lists to functions.